package com.hxzy.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxzy.common.constants.MarketConstants;
import com.hxzy.common.enums.AccountTypeEnum;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.common.resp.R;
import com.hxzy.common.util.MarketThreadLocalUtil;
import com.hxzy.common.util.PwdExecuteFactory;
import com.hxzy.controller.admin.login.req.AdminLoginReq;
import com.hxzy.controller.admin.login.resp.AdminLoginResp;
import com.hxzy.controller.admin.merchandiser.req.MerchandiserChangePwdReq;
import com.hxzy.controller.admin.merchandiser.req.MerchandiserEditReq;
import com.hxzy.controller.admin.merchandiser.req.MerchandiserSearchReq;
import com.hxzy.controller.admin.merchandiser.req.ProcessReq;
import com.hxzy.controller.admin.merchandiser.resp.MerchandiserResp;
import com.hxzy.controller.admin.upload.req.ImagePrivateReq;
import com.hxzy.controller.anonymous.merchandiser.req.AnonyMerchandiserInfoReq;
import com.hxzy.controller.anonymous.merchandiser.req.AnonyMerchandiserSearchReq;
import com.hxzy.controller.anonymous.merchandiser.req.MerchandiserAddReq;
import com.hxzy.controller.anonymous.merchandiser.resp.AnonyMerchandiserResp;
import com.hxzy.controller.anonymous.upload.AnonyTencentUploadController;
import com.hxzy.entity.EnterpriseProcess;
import com.hxzy.entity.Merchandiser;
import com.hxzy.mapstruct.MerchandiserMapStruct;
import com.hxzy.service.EnterpriseProcessService;
import com.hxzy.service.MerchandiserService;
import com.hxzy.mapper.MerchandiserMapper;
import com.hxzy.service.SmsService;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.region.Region;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* @author admin
* @description 针对表【merchandiser(商家信息)】的数据库操作Service实现
* @createDate 2024-02-21 11:30:41
*/
@Log4j2
@Service
public class MerchandiserServiceImpl extends ServiceImpl<MerchandiserMapper, Merchandiser>
    implements MerchandiserService{

    @Autowired
    private PwdExecuteFactory pwdExecuteFactory;

    @Autowired
    private EnterpriseProcessService enterpriseProcessService;

    /**
     * 短信服务
     */
    @Autowired
    private SmsService smsService;

    @Override
    public AdminLoginResp login(AdminLoginReq req) {
        //1、根据用户名查询信息
        //1)、创建mybatisplus查询对象
        LambdaQueryWrapper<Merchandiser> queryWrapper = new LambdaQueryWrapper<>();
        //2)、设置查询条件
        queryWrapper.eq(Merchandiser::getLoginName,req.getLoginName());
        //3)、取得结果
        Merchandiser db = this.getOne(queryWrapper);

        if(Objects.isNull(db)){
            throw new ServiceException(AckCode.LOGIN_ACCOUNT_PASSWORD_ERROR);
        }

//        //2、根据返回结果判断密码是否正确
//        if(!BCrypt.checkpw(req.getLoginPwd(),   db.getLoginPwd())){
//            throw new ServiceException(AckCode.LOGIN_ACCOUNT_PASSWORD_ERROR);
//        }
        this.pwdExecuteFactory.execute(req.getLoginPwd(),db.getLoginPwd(),db.getId(), AccountTypeEnum.MERCHANDISER);

        //3、判断账户状态
        if(MarketConstants.MERCHANDISER_ACCOUNT_NOT_VERIFIED.equals(db.getStatus())){
            throw new ServiceException(AckCode.MERCHANDISER_ACCOUNT_NOT_VERIFIED);
        }else if(MarketConstants.MERCHANDISER_ACCOUNT_VERIFIED_FAILED.equals(db.getStatus())){
            throw new ServiceException(AckCode.MERCHANDISER_ACCOUNT_VERIFIED_FAILED);
        }

        //4、组装自定义对象
        AdminLoginResp   loginResp=new AdminLoginResp();
        loginResp.setId(db.getId());
        loginResp.setName(db.getName());
        loginResp.setRoot(MarketConstants.ACCOUNT_NORMAL);
        loginResp.setAvatar(db.getPicture());
        loginResp.setPermissions(MarketConstants.ACCOUNT_MERCHANDISER_TYPE);

        return loginResp;
    }

    /**
     * 查询账号是否存在
     * @param mobile
     * @return
     */
    @Override
    public long existsAccount(String mobile) {
        LambdaQueryWrapper<Merchandiser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Merchandiser::getLoginName,mobile);
        return this.count(queryWrapper);
    }

    /**
     * 商户注册
     * @param req
     * @return
     */
    @Override
    public boolean register(MerchandiserAddReq req) {
        //判断账户是否存在
        if(this.existsAccount(req.getLoginName())>0L){
            throw new ServiceException(AckCode.EXISTS_VALUE_ACCOUNT);
        }
        Merchandiser entity = MerchandiserMapStruct.INSTANCE.convert(req);
        entity.setStatus(MarketConstants.MERCHANDISER_ACCOUNT_NOT_VERIFIED);
        entity.setLoginPwd(BCrypt.hashpw(req.getLoginPwd()));
        entity.setCreateBy(req.getLoginName());
        entity.setCreateTime(new Date());
        return this.save(entity);
    }


    /**
     * 商家查询
     * @param req
     * @return
     */
    @Override
    public List<MerchandiserResp> search(MerchandiserSearchReq req) {
        List<Merchandiser> list= this.baseMapper.search(req);

        //        List<MerchandiserResp> collect=new ArrayList<>();
        //        for(Merchandiser p : list){
        //            MerchandiserResp  mp=new MerchandiserResp( p);
        //            collect.add(mp);
        //        }

        //做处理
        List<MerchandiserResp> collect = list.stream().map(p -> new MerchandiserResp(p)).collect(Collectors.toList());

        return collect;
    }

    /**
     * 根据请求参数，查询数据库图片的路径
     * @param req
     * @return
     */
    @Override
    public String searchImageKey(ImagePrivateReq req) {
        String key= this.baseMapper.searchImageKey(req);
        if(Objects.isNull(key)){
            throw new ServiceException(AckCode.NOT_FOUND_DATA);
        }
        return key;
    }

    /**
     * 管理员审核商家信息(2个表都要操作，满足事务原子性的概念)
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean process(ProcessReq req) {
        Merchandiser db = this.getById(req.getId());
        if(Objects.isNull(db)){
            throw new ServiceException(AckCode.NOT_FOUND_DATA);
        }

        //不允许再审核
        if(db.getStatus().equalsIgnoreCase(MarketConstants.ACCOUT_DISABLE)){
            throw new ServiceException(AckCode.MERCHANDISER_ACCOUNT_STATUS_ERROR);
        }
        
        db.setUpdateBy(MarketThreadLocalUtil.ADMIN_THREAD_LOCAL.get().getName());
        db.setUpdateTime(new Date());
        db.setStatus(req.getStatus());
        this.updateById(db);

        //新增审核备注
        EnterpriseProcess  enterpriseProcess=new EnterpriseProcess();
        enterpriseProcess.setStatus(req.getStatus());
        enterpriseProcess.setDescription(req.getDescription());
        enterpriseProcess.setTenantId(req.getId());
        enterpriseProcess.setCreateBy(MarketThreadLocalUtil.ADMIN_THREAD_LOCAL.get().getName());
        enterpriseProcess.setCreateTime(new Date());

        boolean result= this.enterpriseProcessService.save(enterpriseProcess);
        //发短信通知，通过
        if(req.getStatus().equalsIgnoreCase(MarketConstants.ACCOUT_DISABLE)){
            this.smsService.approvalPass(db.getLoginName());
        }else{
            //不通过
            this.smsService.approvalNoPass(db.getLoginName(),req.getDescription());
        }
        return result;

    }

    @Override
    public boolean changePassword(MerchandiserChangePwdReq req) {
        if(!req.getNewPwd().equals(req.getRePwd())){
            throw new ServiceException(AckCode.SET_PASSWORD_INVALID);
        }
        AdminLoginResp adminLoginResp = MarketThreadLocalUtil.ADMIN_THREAD_LOCAL.get();
        Merchandiser entity=new Merchandiser();
        entity.setLoginPwd(BCrypt.hashpw(req.getNewPwd()));
        entity.setUpdateTime(new Date());
        entity.setUpdateBy(adminLoginResp.getName());
        entity.setId(adminLoginResp.getId());
        return this.updateById(entity);
    }

    /**
     * 获取当前商家信息
     * @return
     */
    @Override
    public MerchandiserResp findById() {
        AdminLoginResp adminLoginResp = MarketThreadLocalUtil.ADMIN_THREAD_LOCAL.get();
        Merchandiser db = this.getById(adminLoginResp.getId());
        return   new MerchandiserResp(db);
    }

    /**
     * 更新商家信息
     * @param req
     * @return
     */
    @Override
    public boolean updateData(MerchandiserEditReq req) {
        AdminLoginResp adminLoginResp = MarketThreadLocalUtil.ADMIN_THREAD_LOCAL.get();

        Merchandiser db = this.getById(req.getId());


        Merchandiser entity = MerchandiserMapStruct.INSTANCE.convert(req);
        //身份证正面没有改过
        if(StrUtil.isBlank(entity.getIdcardFrontUuid())){
            entity.setIdcardFront(null);
        }else{
            //删除私有图片中的图片
            deletePrivateBucketImage(db.getIdcardFront());

        }

        //身份证背面没有改过
        if(StrUtil.isBlank(entity.getIdcardBackUuid())){
            entity.setIdcardBack(null);
        }else{
            //删除私有图片中的图片
            deletePrivateBucketImage(db.getIdcardBack());
        }

        //营业执照没有改过
        if(StrUtil.isBlank(entity.getBussinessLicenseUuid())){
            entity.setBussinessLicense(null);
        }else{
            //删除私有图片中的图片
            deletePrivateBucketImage(db.getBussinessLicense());
        }

        entity.setUpdateBy(adminLoginResp.getUuid());
        entity.setUpdateTime(new Date());

        return this.updateById(entity);
    }

    @Override
    public List<AnonyMerchandiserResp> anonySearch(AnonyMerchandiserSearchReq req) {
        return this.baseMapper.anonySearch(req);
    }

    /**
     * 查询商家信息
     * @param req
     * @return
     */
    @Override
    public AnonyMerchandiserResp findByInfo(AnonyMerchandiserInfoReq req) {
        return this.baseMapper.anonyFindByInfo(req);
    }


    private void deletePrivateBucketImage(String key){
        // 调用 COS 接口之前必须保证本进程存在一个 COSClient 实例，如果没有则创建
        // 详细代码参见本页：简单操作 -> 创建 COSClient
        COSClient cosClient = AnonyTencentUploadController.createCOSClient();

        // 对象键(Key)是对象在存储桶中的唯一标识。详情请参见 [对象键](https://cloud.tencent.com/document/product/436/13324)
        try {
            cosClient.deleteObject(AnonyTencentUploadController.PRIVATE_BUCKET_NAME, key);
        } catch (CosClientException e) {
            log.error(e);
            throw new ServiceException(AckCode.REMOVE_FILE_ERROR);
        }finally {
            // 确认本进程不再使用 cosClient 实例之后，关闭即可
            cosClient.shutdown();
        }
    }



}





